/*  
 *  Vector3D.cpp
 *
 *  Created by Pete Willemsen on 01/19/2011.
 *  Copyright 2011 Department of Computer Science, University of Minnesota Duluth. All rights reserved.
 *
 * This file is part of CS5721 Computer Graphics library (cs5721Graphics).
 *
 * cs5721Graphics is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * cs5721Graphics is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with cs5721Graphics.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "Vector3D.h"
#include <math.h>

using namespace std;

namespace cs5721 {

    ostream & operator<<(ostream& os, const cs5721::Vector3D& v) {
        os << '[' << v[0] << ' ' << v[1] << ' ' << v[2] << ']';
        return os;
    }

    istream & operator>>(istream& is, cs5721::Vector3D& v) {
        double x = 0, y = 0, z = 0;
        is >> x >> y >> z;
        v.set(x, y, z);
        return is;
    }

    const cs5721::Vector3D operator+(const cs5721::Vector3D &lhs, const cs5721::Vector3D &rhs) {
        return cs5721::Vector3D(lhs) += rhs;
    }

    const cs5721::Vector3D operator-(const cs5721::Vector3D &lhs, const cs5721::Vector3D &rhs) {
        return cs5721::Vector3D(lhs) -= rhs;
    }

    const cs5721::Vector3D operator*(const cs5721::Vector3D& lhs, const double c) {
        return cs5721::Vector3D(lhs) *= c;
    }

    const cs5721::Vector3D operator/(const cs5721::Vector3D &lhs, const double c) {
        return cs5721::Vector3D(lhs) /= c;
        ;
    }
}

using namespace cs5721;

double Vector3D::normalize(void) {
    const double vector_length = sqrt(data[0] * data[0] +
            data[1] * data[1] +
            data[2] * data[2]);
    if (vector_length > 0.0) {
        data[0] /= vector_length;
        data[1] /= vector_length;
        data[2] /= vector_length;
    }

    return vector_length;
}

//Clamps the highest value to 1.0 and keeps respected ratios between components
//Used specifically when representing a (r,g,b) color.

void Vector3D::clamp() {
    bool simple = true;
    double exposure = -1.0;

    if (simple) {
        if(data[0] > 1.0) data[0] = 1.0;
        if(data[1] > 1.0) data[1] = 1.0;
        if(data[2] > 1.0) data[2] = 1.0;
    } else {
        if (data[0] > 1.0 || data[1] > 1.0 || data[2] > 1.0) {
            data[0] = 1.0 - exp(data[0] * exposure);
            data[1] = 1.0 - exp(data[1] * exposure);
            data[2] = 1.0 - exp(data[2] * exposure);
        }
    }
}

